import java.io.IOException;

import javax.bluetooth.BluetoothStateException;
import javax.bluetooth.DataElement;
import javax.bluetooth.DiscoveryAgent;
import javax.bluetooth.LocalDevice;
import javax.bluetooth.ServiceRecord;
import javax.bluetooth.UUID;
import javax.microedition.io.Connector;
import javax.microedition.io.StreamConnection;
import javax.microedition.io.StreamConnectionNotifier;




/**
 * @author mathieu
 * A easy way to create a Bluetooth server.
 */
public  class BluetoothServer {

	private int type;
	private UUID uuid;
	private String connectionURL;
	private StreamConnectionNotifier server = null;
	private ServiceRecord sr;
	private LocalDevice local = null;
	private String className;
	
	
	/**
	 * Create a bluetooth server
	 * 
	 * @param uuid the uuid of the service you want to create (could be generate by the uuidgen -t command under UNIX) 
	 * @param connectionUrl The full address ( btspp://[BLUETOOTHADDRESS]:[UUID];[PARAM] ) exemple :btspp://localhost:b4c865ce9d3711dcac090019e06863dd;authenticate=false;encrypt=false;name=RFCOMM Server". 
	 * @param className The name of a class which extends the ServerConnectionDialer class and which will deal with the connection anytime a client connect to the server
	 */
	public BluetoothServer (UUID uuid,String connectionUrl, String className){
		this.uuid = uuid;
		this.connectionURL = connectionUrl;
		this.className = className;
		type = EasyAwarenessInput.BLUETOOTH;
		try {
			local = LocalDevice.getLocalDevice();
			local.setDiscoverable(DiscoveryAgent.GIAC);
		} catch (BluetoothStateException e) {
			e.printStackTrace();
		}
		
		launchServer serverRun = new launchServer();
		new Thread(serverRun).start();
	}
	public class launchServer implements Runnable {
		public launchServer(){
			super();
		}
		public void run(){
			try {
				server = (StreamConnectionNotifier)Connector.open(connectionURL);
				try {
					sr = local.getRecord(server);
				}
				catch (IllegalArgumentException iae){
					iae.printStackTrace();
				}
				catch(NullPointerException npe){
					npe.printStackTrace();
				}
				DataElement elm = new DataElement(DataElement.UUID, uuid);
				sr.setAttributeValue(0x0003,elm);
			} catch (IOException e) {
				e.printStackTrace();
			}
			while(true){
				StreamConnection conn = null;
				try {
					conn = server.acceptAndOpen();
					Class classStub = null;
					try {
						 classStub = Class.forName(className);
					} catch (ClassNotFoundException e) {
						e.printStackTrace();
					}
					ServerConnectionDialer dial = (ServerConnectionDialer)classStub.newInstance();
					dial.setConn(conn);
					new Thread(dial).start();
				} catch (IOException e) {
					e.printStackTrace();
				} catch (InstantiationException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				}

			}

		}
	}
	
	
	public int getType() {
		return type;
	}


}
